import 'dart:convert';
import 'dart:io';

import 'package:device_info_plus/device_info_plus.dart';
import 'package:package_info_plus/package_info_plus.dart';
import 'package:ride_rex/net/common_global_url.dart';
import 'package:ylm_ui_kit/ylm_ui_kit.dart';

import '../constant.dart';
import '../ui/common_dialogs.dart';
import 'common_net.dart';

class DeviceInfoUtils {
  DeviceInfoUtils._internal();

  factory DeviceInfoUtils() => _instance;

  static final DeviceInfoUtils _instance = DeviceInfoUtils._internal();

  final DeviceInfoPlugin _deviceInfo = DeviceInfoPlugin();

  String deviceId = '';
  String deviceModel = '';
  String deviceLanguageCode = '';

  Future init() async {
    if (Platform.isAndroid) {
      AndroidDeviceInfo androidInfo = await _deviceInfo.androidInfo;
      deviceId = androidInfo.id;
      deviceModel = androidInfo.model;
    } else if (Platform.isIOS) {
      IosDeviceInfo iosInfo = await _deviceInfo.iosInfo;
      deviceId = iosInfo.identifierForVendor ?? '';
      deviceModel = iosInfo.utsname.machine;
    }

    List<String> languageCode = Platform.localeName.split('_');
    if (languageCode.isNotEmpty) {
      deviceLanguageCode = languageCode.first;
    } else {
      deviceLanguageCode = Platform.localeName;
    }
  }
}

class PackageInfoUtils {
  PackageInfoUtils._internal();

  factory PackageInfoUtils() => _instance;

  static final PackageInfoUtils _instance = PackageInfoUtils._internal();

  String packageName = '';
  String version = '';
  String build = '';

  Future init() async {
    final PackageInfo packageInfo = await PackageInfo.fromPlatform();
    packageName = packageInfo.packageName;
    version = packageInfo.version;
    build = packageInfo.buildNumber;
  }
}

///提供netBuilder
abstract class CoreNetBuilder extends CommonNetBuilder {
  String? version;
  String? identity;

  @override
  Future<Map<String, dynamic>> initHeaders() async {
    Map<String, dynamic> headers = {};
    headers['device-id'] = DeviceInfoUtils().deviceId; // 设备id或者udid，保证当前设备唯一值
    if (Platform.isAndroid) {
      headers['platform'] = 'Android';
    } else if (Platform.isIOS) {
      headers["platform"] = "iOS";
    }
    headers['model'] = DeviceInfoUtils().deviceModel; // 设备型号
    headers['pkg'] = PackageInfoUtils().packageName; // 包名
    headers['ver'] = PackageInfoUtils().version; // 版本 例如1.0.0，读取实际配置的版本号
    headers['p_ver'] = PackageInfoUtils().build; // build number
    headers['kst'] = '1'; // 固定传1
    headers['sys_lan'] = DeviceInfoUtils().deviceLanguageCode; // 手机系统语言 如英文en
    headers['lang'] = DeviceInfoUtils().deviceLanguageCode; // 手机系统语言 如英文en
    headers['Authorization'] = 'Bearer${CommonStorage().getString(StorageKey.spKeyToken, defaultValue: '')}';
    headers['content-type'] = 'application/json';

    return headers;
  }

  ///throw Exception(); 可以让下一步的[showError]不进行弹窗提示
  @override
  Future reduceJson(dynamic result) async {
    Map json;
    if (result is String) {
      json = jsonDecode(result);
    } else {
      json = result;
    }

    int code = json['code'];
    String msg = json['msg'] ?? "Request error，$code";

    ///请求成功
    if (code == 0) {
      if (json.containsKey("data")) {
        return json["data"];
      } else {
        return json;
      }
    }

    ///未提供token、token格式错误、无效token、token过期、其他设备登录
    if (code == 10010301 || code == 10010302 || code == 100103 || code == 10010303 || code == 10010304) {
      CommonDialogs.showLoginDialog();
      return CommonNetOtherError();
    }

    ///token为空
    if (code == 10010307) {
      return CommonNetOtherError();
    }

    ///金币不足
    if (code == 20010009) {
      throw Exception(msg);
    }

    throw Exception(msg);
  }

  @override
  void showError(CommonNetError errorType, Exception error) {
    switch (errorType) {
      case CommonNetError.netError:
        Loading.toast('Please check the network connection');
        return;
      case CommonNetError.connectTimeout:
        Loading.toast('Connection timeout');
        return;
      case CommonNetError.sendTimeout:
        Loading.toast('Send timeout');
        return;
      case CommonNetError.receiveTimeout:
        Loading.toast('Receive timeout');
        return;
      case CommonNetError.formatError:
        Loading.toast('Data format error');
        return;
      case CommonNetError.cancel:
        Loading.toast('Request cancel');
        return;
      case CommonNetError.other:
      default:
        if (error.toString() == 'Exception') return;
        Loading.toast(
          error.toString().replaceAll("Exception: ", ""),
        );
        return;
    }
  }

  @override
  void print(msg) {
    Log.log('----- net error ----- :$msg');
  }
}

class LinkNetBuilder extends CoreNetBuilder {
  @override
  String getBaseUrl() => CommonGlobalUrl.apiBaseRelease;

  @override
  Future<Map<String, dynamic>> initAutoPostParams() async => Future.value({});
}

class DebugNetBuilder extends CoreNetBuilder {
  DebugNetBuilder(this.mode);

  final DebugMode mode;

  @override
  String getBaseUrl() => DebugMode.debug == mode ? CommonGlobalUrl.apiBaseDebug : CommonGlobalUrl.apiBaseRelease;

  @override
  Future<Map<String, dynamic>> initAutoPostParams() async => Future.value({});
}

enum DebugMode {
  debug,
  release,
}
